package com.zslibrary.Protocol;

import android.util.Log;
import android.util.SparseArray;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.zslibrary.Enum.PropertyDefine;
import com.zslibrary.Structure.ComponentStruct;
import com.zslibrary.Structure.ConfigRecipeStrcut;
import com.zslibrary.Structure.CraftBriefStruct;
import com.zslibrary.Structure.CraftStrcut;
import com.zslibrary.Structure.GateStruct;
import com.zslibrary.Structure.IngredientStruct;
import com.zslibrary.Structure.JoblistStruct;
import com.zslibrary.Structure.ProdComponentStruct;
import com.zslibrary.Structure.ProductInfoStruct;
import com.zslibrary.Structure.TreeDefineStruct;
import com.zslibrary.Tools.ZSLog;

public class JobList {

    public static ProductInfoStruct generateJoblist(ConfigRecipeStrcut[] recipe, int craftId){
        ProductInfoStruct productInfo=null;
        ConfigRecipeStrcut[] classfiedRecipes=new ConfigRecipeStrcut[recipe.length];
        if((recipe==null)||(recipe.length==0)){
            ZSLog.d("recipe no found");
            return productInfo;
        }
        for(int i=0;i<recipe.length;i++){
            ComponentStruct componentInfo=Machine.getComponentInfo(recipe[i].componentId);
            if(componentInfo==null){
                //ZSLog.d( "get component:"+(recipe[i].componentId));
                return productInfo;
            }
            if(!componentInfo.configurable)
                return productInfo;   /*无法配置的component，出错*/
            ConfigRecipeStrcut r=new ConfigRecipeStrcut();
            for(int j=0;j<i;j++){
                if(classfiedRecipes[j].componentId==recipe[i].componentId){
                    r.step=++classfiedRecipes[j].step;
                    break;
                }
            }
            r.componentId=recipe[i].componentId;
            r.dosage=recipe[i].dosage;
            r.property=recipe[i].property;
            classfiedRecipes[i]=r;
        }

        int recipeUsedNum=0;
        SparseArray<CraftStrcut> crafts=Machine.getCrafts();
        CraftStrcut craft=crafts.get(craftId);
        if(craft==null){
            ZSLog.d("craft no found");
            return productInfo;   /*错误的工艺ID*/
        }
        SparseArray<IngredientStruct> ingrDescription=Machine.getIngrDescription();
        JoblistStruct[] joblists=new JoblistStruct[craft.prodComponent.length];
        TreeDefineStruct[] trees=new TreeDefineStruct[craft.prodComponent.length];
        int treeLength=0;
        int joblistLength=0;
        Boolean hasSolvent=false;
        /*遍历工艺*/
        for(int i=0;i<craft.prodComponent.length;i++){
            ProdComponentStruct prodComponent=craft.prodComponent[i];
            ComponentStruct componentInfo=Machine.getComponentInfo(prodComponent.parent.componentId);
            /*溶剂类型不需要判断*/
            if(componentInfo.configurable&&(!searchComponentFromRecipe(recipe,prodComponent.parent.componentId))&&(componentInfo.property!=PropertyDefine.SOLVENT_INGR))
                continue;
            TreeDefineStruct tree=new TreeDefineStruct();
            JoblistStruct joblist;
            Boolean[] anyComponentExist={false,false};
            for(int k=0;k<joblists.length;k++){
                if(joblists[k]!=null){
                    if(joblists[k].componentId==prodComponent.me.componentId){
//                        joblist.transformation++;
                        /*TODO:有问题*/
                        if(prodComponent.me.fluid+1>joblists[k].transformation)
                            joblists[k].transformation=(byte)(prodComponent.me.fluid+1);
                        anyComponentExist[0]=true;
                    }else if(joblists[k].componentId==prodComponent.parent.componentId){
                        if(componentInfo.configurable){
                            int dosage=0;
                            /*溶剂只使用第一段dosage*/
                            if(componentInfo.property==PropertyDefine.SOLVENT_INGR){
                                if(!hasSolvent){
                                    hasSolvent=true;
                                    recipeUsedNum++;
                                    dosage=searchDosageFromRecipe(classfiedRecipes,prodComponent);
                                }
                                else
                                    dosage=1;
                            }else{
                                dosage=searchDosageFromRecipe(classfiedRecipes,prodComponent);    /*非溶剂类型多段都要使用*/
                                recipeUsedNum++;
                            }

                            if(dosage<0) {
                                ZSLog.d("recipe wrong");
                                return productInfo;
                            }
                            joblists[k].dosage[prodComponent.parent.fluid]=(short)dosage;
                        }
                        else
                            joblists[k].dosage[prodComponent.parent.fluid]=(short)-3;
                        joblists[k].ingredient[prodComponent.parent.fluid]=(short)ingrDescription.get(prodComponent.ingredient.descriptionId).property;
                        joblists[k].unit[prodComponent.parent.fluid]=(short)ingrDescription.get(prodComponent.ingredient.descriptionId).unitType;
//                        joblist.transformation++;
                        /*TODO:有问题*/
                        if(prodComponent.parent.fluid+1>joblists[k].transformation)
                            joblists[k].transformation=(byte)(prodComponent.parent.fluid+1);
                        anyComponentExist[1]=true;
                    }
                }
            }
            if(!anyComponentExist[0]){
                joblist=new JoblistStruct();
                joblist.componentId=(short)prodComponent.me.componentId;
                joblist.transformation=1;
                /*将所有的数据初始化填充*/
                Arrays.fill(joblist.dosage, (short) 0xFFFD);
                Arrays.fill(joblist.ingredient, (short) 0);
                Arrays.fill(joblist.unit, (short) 0);
                joblist.dosage[prodComponent.me.fluid]=(short)0xFFFD;
                joblist.ingredient[prodComponent.me.fluid]=(short)0;
                joblist.unit[prodComponent.me.fluid]=(short)0;
                joblists[joblistLength++]=joblist;
            }
            if(!anyComponentExist[1]){
                joblist=new JoblistStruct();
                joblist.componentId=(short)prodComponent.parent.componentId;
                joblist.transformation=1;
                /*将所有的数据初始化填充*/
                Arrays.fill(joblist.dosage, (short) 0xFFFD);
                Arrays.fill(joblist.ingredient, (short) 0);
                Arrays.fill(joblist.unit, (short) 0);
//                    joblist.dosage[prodComponent.me.fluid]=(short)prodComponent.ingredient.std;
                if(componentInfo.configurable){
                    /*溶剂只使用第一段dosage*/
                    int dosage;
                    if(componentInfo.property==PropertyDefine.SOLVENT_INGR){
                        if(!hasSolvent){
                            hasSolvent=true;
                            recipeUsedNum++;
                            dosage=searchDosageFromRecipe(classfiedRecipes,prodComponent);
                        }else
                            dosage=1;
                    }else{
                        dosage=searchDosageFromRecipe(classfiedRecipes,prodComponent);
                        recipeUsedNum++;
                    }
                    if(dosage<0){
                        ZSLog.d("recipe wrong");
                        return productInfo;
                    }
                    else if(dosage==0)
                        continue;
                    joblist.dosage[prodComponent.parent.fluid]=(short)dosage;
                }
                else
                    joblist.dosage[prodComponent.parent.fluid]=(short)-3;
                joblist.ingredient[prodComponent.parent.fluid]=(short)ingrDescription.get(prodComponent.ingredient.descriptionId).property;
                joblist.unit[prodComponent.parent.fluid]=(short)ingrDescription.get(prodComponent.ingredient.descriptionId).unitType;
                joblists[joblistLength++]=joblist;
            }
            /*tree info*/
            if(prodComponent.parent==null){
                continue;
            }
            GateStruct gate=new GateStruct();
            gate.componentId=(short)prodComponent.parent.componentId;
            gate.gateId=(byte)prodComponent.parent.gateId;
            tree.sender=gate;
            /*TODO:有问题*/
            tree.sendTreeNr=(byte)prodComponent.parent.fluid;
            tree.sendFlow=(short)searchFlow(gate.componentId,gate.gateId);
            gate=new GateStruct();
            gate.componentId=(short) prodComponent.me.componentId;
            gate.gateId=(byte)prodComponent.me.gateId;
            tree.receiver=gate;
            tree.receiveTreeNr=(byte)prodComponent.me.fluid;
            tree.receiveFlow=(short)searchFlow(gate.componentId,gate.gateId);
            trees[treeLength++]=tree;
        }
        if(recipeUsedNum!=classfiedRecipes.length){
            ZSLog.d("recipe match failed");
            return productInfo;   /*该配方不匹配该工艺*/
        }
        productInfo=new ProductInfoStruct();
        productInfo.circles=1;
        productInfo.productId=(short)craft.id;
        productInfo.joblist=joblists;
        productInfo.tree=trees;
        productInfo.joblistsLength=(short)joblistLength;
        productInfo.treeLength=(short)treeLength;
        return productInfo;
    }

//    public static List<ConfigRecipeStrcut> getConfigurableComponents(int craftId){
//        List<ConfigRecipeStrcut> componentInfos=null;
//        SparseArray<CraftStrcut> crafts=Machine.getCrafts();
//        if(crafts!=null){
//            CraftStrcut craft=crafts.get(craftId);
//            componentInfos=new LinkedList<ConfigRecipeStrcut>();
//            Boolean hasSolvent=false;
//            for(int i=0;i<craft.prodComponent.length;i++){
//                ProdGateStruct prodComponent=craft.prodComponent[i].parent;
//                if(!Machine.getComponentInfo(prodComponent.componentId).configurable)
//                    continue;
//                if(Machine.getComponentInfo(prodComponent.componentId).property==PropertyDefine.SOLVENT_INGR){
//                    if(hasSolvent)  /*溶剂只添加一次*/
//                        continue;
//                    hasSolvent=true;
//                }
//                ConfigRecipeStrcut parentComponentInfo=new ConfigRecipeStrcut();
//                parentComponentInfo.componentId=prodComponent.componentId;
//                parentComponentInfo.property=Machine.getComponentInfo(prodComponent.componentId).property;
////                parentComponentInfo.step=prodComponent.fluid;
//                parentComponentInfo.dosage=craft.prodComponent[i].ingredient.std;
//                componentInfos.add(parentComponentInfo);
//            }
//        }
//        return componentInfos;
//    }

    public static List<CraftBriefStruct> getAllCraftDesciption(){
        List<CraftBriefStruct> briefCrafts=new ArrayList<>();
        SparseArray<CraftStrcut> crafts=Machine.getCrafts();
        if(crafts!=null){
            for(int i=0;i<crafts.size();i++){
                CraftBriefStruct brief=new CraftBriefStruct();
                brief.craftId=crafts.valueAt(i).id;
                brief.name=crafts.valueAt(i).name;
                briefCrafts.add(brief);
            }
        }
        return briefCrafts;
    }

    private static int searchDosageFromRecipe(ConfigRecipeStrcut[] recipe,ProdComponentStruct prodComponent){
        for(ConfigRecipeStrcut r:recipe){
            if((r.componentId==prodComponent.parent.componentId)&&(r.property==Machine.getComponentInfo(prodComponent.parent.componentId).property)&&(r.step==prodComponent.parent.fluid)){
                return r.dosage;
            }
        }
        return -3;
    }

    private static int searchFlow(int componentId,int gateId){
        SparseArray<ComponentStruct> components=Machine.getComponentList();
        for(int i=0;i<components.size();i++){
            if(componentId==components.keyAt(i)){
                return components.valueAt(i).gates[gateId].type;
            }
        }
        return -1;
    }

    private static Boolean searchComponentFromRecipe(ConfigRecipeStrcut[] recipe,int componentId){
        for(ConfigRecipeStrcut r:recipe){
            if(r.componentId==componentId)
                return true;
        }
        return false;
    }


}
